package com.orcamento.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;

import javax.persistence.Embeddable;

@Embeddable
public class Money implements Comparable<Money> {

	private BigDecimal value;
	
	public Money() {
		this.value = BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP);
	}
	
	public Money(Integer value) {
		this.value = BigDecimal.valueOf(value).setScale(2, BigDecimal.ROUND_HALF_UP);
	}
	
	public Money(Double value) {
		this.value = BigDecimal.valueOf(value).setScale(2, BigDecimal.ROUND_HALF_UP);
	}
	
	public Money(String maskValue) {
		maskValue = maskValue.replace("R$ ", "").replaceAll("\\.", "").replace(",", ".");
		maskValue = getFormarter().format( Double.valueOf( maskValue ) );
		
		this.value = new BigDecimal( maskValue ).setScale(2, BigDecimal.ROUND_HALF_UP);
	}
	
	public Money(BigDecimal value) {
		this.value = value.setScale(2, BigDecimal.ROUND_HALF_UP);
	}
	
	public Money plus(Money money) {
		return new Money( value.add( money.toBigDecimal() ) );
	}

	public Money minus(Money money) {
		return new Money( value.subtract( money.toBigDecimal() ) );
	}
	
	public Money multiply(BigDecimal product) {
		return new Money( value.multiply(product).setScale(2, BigDecimal.ROUND_HALF_UP) );
	}

	public Money divide(BigDecimal divisor) {
		return new Money( value.divide( divisor, 2, RoundingMode.HALF_EVEN ) );
	}

	public BigDecimal toBigDecimal() {
		return value;
	}
	
	public Double toDouble() {
		return value.doubleValue();
	}
	
	@Override
	public String toString() {
		return NumberFormat.getCurrencyInstance(new Locale("pt", "BR")).format(value);
	}

	private DecimalFormat getFormarter() {
		DecimalFormatSymbols decimalSymbol = DecimalFormatSymbols.getInstance();
		decimalSymbol.setDecimalSeparator( '.' );
		DecimalFormat formater = new DecimalFormat("#.##");
		formater.setDecimalFormatSymbols( decimalSymbol );
		return formater;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + value.hashCode();
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Money other = (Money) obj;
		if (!value.equals(other.value))
			return false;
		return true;
	}

	public boolean isZero() {
		return equals( new Money(0) );
	}

	public boolean greaterThan(Money anotherMoney) {
		return compareTo( anotherMoney ) > 0;
	}

	@Override
	public int compareTo(Money anotherMoney) {
		return value.compareTo( anotherMoney.value );
	}

	public boolean greaterThanZero() {
		return greaterThan( new Money() );
	}

}